home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility1 / gs261src.zip / GXCLIST.C < prev    next >
C/C++ Source or Header  |  1993-05-26  |  26KB  |  799 lines

  1. /* Copyright (C) 1991, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* gxclist.c */
  20. /* Command list writing for Ghostscript. */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gpcheck.h"
  24. #include "gserrors.h"
  25. #include "gxdevice.h"
  26. #include "gxdevmem.h"            /* must precede gxclist.h */
  27. #include "gxcldev.h"
  28.  
  29. /* Forward declarations of procedures */
  30. private dev_proc_open_device(clist_open);
  31. private dev_proc_get_initial_matrix(clist_get_initial_matrix);
  32. private dev_proc_output_page(clist_output_page);
  33. private dev_proc_map_rgb_color(clist_map_rgb_color);
  34. private dev_proc_map_color_rgb(clist_map_color_rgb);
  35. private dev_proc_fill_rectangle(clist_fill_rectangle);
  36. private dev_proc_tile_rectangle(clist_tile_rectangle);
  37. private dev_proc_copy_mono(clist_copy_mono);
  38. private dev_proc_copy_color(clist_copy_color);
  39. extern dev_proc_get_bits(clist_get_bits);    /* in gxclread.c */
  40. private dev_proc_get_props(clist_get_props);
  41. private dev_proc_put_props(clist_put_props);
  42. private dev_proc_map_cmyk_color(clist_map_cmyk_color);
  43. private dev_proc_get_xfont_procs(clist_get_xfont_procs);
  44. private dev_proc_get_xfont_device(clist_get_xfont_device);
  45.  
  46. /* The device descriptor */
  47. /* The device template itself is never used, only the procs. */
  48. gx_device_procs gs_clist_device_procs =
  49. {    clist_open,
  50.     clist_get_initial_matrix,
  51.     gx_default_sync_output,
  52.     clist_output_page,
  53.     gx_default_close_device,
  54.     clist_map_rgb_color,
  55.     clist_map_color_rgb,
  56.     clist_fill_rectangle,
  57.     clist_tile_rectangle,
  58.     clist_copy_mono,
  59.     clist_copy_color,
  60.     gx_default_draw_line,
  61.     clist_get_bits,
  62.     clist_get_props,
  63.     clist_put_props,
  64.     clist_map_cmyk_color,
  65.     clist_get_xfont_procs,
  66.     clist_get_xfont_device
  67. };
  68.  
  69. /* ------ Define the command set and syntax ------ */
  70.  
  71. #ifdef DEBUG
  72. const char *cmd_op_names[16] = { cmd_op_name_strings };
  73. const char *cmd_misc_op_names[16] = { cmd_misc_op_name_strings };
  74. private ulong cmd_op_counts[256];
  75. private ulong cmd_tile_count, cmd_copy_count, cmd_delta_tile_count;
  76. private ulong cmd_tile_reset, cmd_tile_found, cmd_tile_added;
  77. private int
  78. count_op(int op)
  79. {    ++cmd_op_counts[op];
  80.     if_debug2('L', ", %s %d\n", cmd_op_names[op >> 4], op & 0xf);
  81.     fflush(dstderr);
  82.     return op;
  83. }
  84. #  define count_add(v, n) (v += (n))
  85. #else
  86. #  define count_op(store_op) store_op
  87. #  define count_add(v, n) 0
  88. #endif
  89. #define count_add1(v) count_add(v, 1)
  90.  
  91. /* Initialize the device state */
  92. private void clist_init_tiles(P1(gx_device_clist *));
  93. private int
  94. clist_open(gx_device *dev)
  95. {    /*
  96.      * The buffer area (data, data_size) holds a tile cache and a
  97.      * set of block range bit masks when both writing and reading.
  98.      * The rest of the space is used for
  99.      * the command buffer and band state bookkeeping when writing,
  100.      * and for the rendering buffer (image device) when reading.
  101.      * For the moment, we divide the space up arbitrarily.
  102.      *
  103.      * This routine requires only data, data_size, target, and mdev
  104.      * to have been set in the device structure, and is idempotent,
  105.      * so it can be used to check whether a given-size buffer
  106.      * is large enough.
  107.      */
  108.     byte *data = cdev->data;
  109.     uint size = cdev->data_size;
  110. #define alloc_data(n) data += (n), size -= (n)
  111.     gx_device *target = cdev->target;
  112.     uint raster, nbands, band;
  113.     gx_clist_state *states;
  114.     ulong state_size;
  115.     cdev->ymin = cdev->ymax = -1;    /* render_init not done yet */
  116.     cdev->tile_data = data;
  117.     cdev->tile_data_size = (size / 5) & -4;    /* arbitrary! */
  118.     alloc_data(cdev->tile_data_size);
  119.     raster = gx_device_raster(target, 1) + sizeof(byte *);
  120.     cdev->band_height = size / raster;
  121.     if ( cdev->band_height == 0 )    /* can't even fit one scan line */
  122.         return_error(gs_error_limitcheck);
  123.     nbands = target->height / cdev->band_height + 1;
  124.     cdev->nbands = nbands;
  125.     if_debug4('l', "[l]width=%d, raster=%d, band_height=%d, nbands=%d\n",
  126.              target->width, raster, cdev->band_height, cdev->nbands);
  127.     state_size = nbands * (ulong)sizeof(gx_clist_state);
  128.     if ( state_size + sizeof(cmd_prefix) + cmd_largest_size + raster + 4 > size )        /* not enough room */
  129.         return_error(gs_error_limitcheck);
  130.     cdev->mdev.base = data;
  131.     cdev->states = states = (gx_clist_state *)data;
  132.     alloc_data((uint)state_size);
  133.     cdev->cbuf = data;
  134.     cdev->cnext = data;
  135.     cdev->cend = data + size;
  136.     cdev->ccls = 0;
  137.     for ( band = 0; band < nbands; band++, states++ )
  138.       *states = cls_initial;
  139. #undef alloc_data
  140.     cdev->tile_band_mask_size = (nbands + 31) / 32 * 4;
  141.     cdev->tile_max_size = cdev->tile_data_size -
  142.         (sizeof(tile_hash) * 2 + sizeof(tile_slot) +
  143.          cdev->tile_band_mask_size);
  144.     clist_init_tiles(cdev);
  145.     return 0;
  146. }
  147.  
  148. /* (Re)initialize the tile cache. */
  149. private void
  150. clist_init_tiles(register gx_device_clist *cldev)
  151. {    gx_clist_state *pcls;
  152.     int i, hc;
  153.     cldev->tile_slot_size =
  154.       sizeof(tile_slot) + cldev->tile_band_mask_size +
  155.       cldev->tile.raster * cldev->tile.size.y;
  156.     cldev->tile_max_count = cldev->tile_data_size /
  157.       (sizeof(tile_hash) * 3 /*(worst case)*/ + cldev->tile_slot_size);
  158.     hc = (cldev->tile_max_count - 1) * 2;
  159.     while ( (hc + 1) & hc ) hc |= hc >> 1;    /* make mask */
  160.     if ( hc >= cldev->tile_max_count * 3 ) hc >>= 1;
  161.     if ( hc > 255 )        /* slot index in set_tile is only 1 byte */
  162.        {    hc = 255;
  163.         if ( cldev->tile_max_count > 200 )
  164.             cldev->tile_max_count = 200;
  165.        }
  166.     cldev->tile_hash_mask = hc;
  167.     hc++;                /* make actual size */
  168.     if_debug5('l', "[l]tile.size=%dx%d, slot_size=%d, max_count=%d, hc=%d\n",
  169.          cldev->tile.size.x, cldev->tile.size.y,
  170.          cldev->tile_slot_size, cldev->tile_max_count, hc);
  171.     cldev->tile_hash_table =
  172.         (tile_hash *)(cldev->tile_data + cldev->tile_data_size) - hc;
  173.     cldev->tile_count = 0;
  174.     memset(cldev->tile_data, 0, cldev->tile_data_size);
  175.     memset(cldev->tile_hash_table, -1, hc * sizeof(tile_hash));
  176.     for ( i = 0, pcls = cldev->states; i < cldev->nbands; i++, pcls++ )
  177.         pcls->tile = &no_tile;
  178.     count_add1(cmd_tile_reset);
  179. }
  180.  
  181. /* Clean up after rendering a page. */
  182. private int
  183. clist_output_page(gx_device *dev, int num_copies, int flush)
  184. {    if ( flush )
  185.        {    rewind(cdev->cfile);
  186.         rewind(cdev->bfile);
  187.         cdev->bfile_end_pos = 0;
  188.        }
  189.     else
  190.        {    fseek(cdev->cfile, 0L, SEEK_END);
  191.         fseek(cdev->bfile, 0L, SEEK_END);
  192.        }
  193.     return clist_open(dev);        /* reinitialize */
  194. }
  195.  
  196. /* Forward the non-displaying operations to the target device. */
  197. private void
  198. clist_get_initial_matrix(gx_device *dev, gs_matrix *pmat)
  199. {    (*cdev->target->procs->get_initial_matrix)(dev, pmat);
  200. }
  201. private gx_color_index
  202. clist_map_rgb_color(gx_device *dev, gx_color_value red, gx_color_value green,
  203.   gx_color_value blue)
  204. {    return (*cdev->target->procs->map_rgb_color)(dev, red, green, blue);
  205. }
  206. private int
  207. clist_map_color_rgb(gx_device *dev, gx_color_index color,
  208.   gx_color_value rgb[3])
  209. {    return (*cdev->target->procs->map_color_rgb)(dev, color, rgb);
  210. }
  211. private int
  212. clist_get_props(gx_device *dev, gs_prop_item *plist)
  213. {    gx_device *tdev = cdev->target;
  214.     return (*tdev->procs->get_props)(tdev, plist);
  215. }
  216. private int
  217. clist_put_props(gx_device *dev, gs_prop_item *plist, int count)
  218. {    gx_device *tdev = cdev->target;
  219.     return (*tdev->procs->put_props)(tdev, plist, count);
  220. }
  221. private gx_color_index
  222. clist_map_cmyk_color(gx_device *dev, gx_color_value cyan,
  223.   gx_color_value magenta, gx_color_value yellow, gx_color_value black)
  224. {    return (*cdev->target->procs->map_cmyk_color)(dev, cyan, magenta, yellow, black);
  225. }
  226. private gx_xfont_procs *
  227. clist_get_xfont_procs(gx_device *dev)
  228. {    gx_device *tdev = cdev->target;
  229.     return (*tdev->procs->get_xfont_procs)(tdev);
  230. }
  231. private gx_device *
  232. clist_get_xfont_device(gx_device *dev)
  233. {    gx_device *tdev = cdev->target;
  234.     return (*tdev->procs->get_xfont_device)(tdev);
  235. }
  236.  
  237. /* Print statistics. */
  238. #ifdef DEBUG
  239. void
  240. cmd_print_stats(void)
  241. {    int ci, cj;
  242.     dprintf3("[l]counts: tile = %ld, copy = %ld, delta = %ld\n",
  243.              cmd_tile_count, cmd_copy_count, cmd_delta_tile_count);
  244.     dprintf3("           reset = %ld, found = %ld, added = %ld\n",
  245.              cmd_tile_reset, cmd_tile_found, cmd_tile_added);
  246.     for ( ci = 0; ci < 0x100; ci += 0x10 )
  247.        {    dprintf1("[l]  %s =", cmd_op_names[ci >> 4]);
  248.         for ( cj = ci; cj < ci + 0x10; cj++ )
  249.             dprintf1(" %ld", cmd_op_counts[cj]);
  250.         dputs("\n");
  251.        }
  252. }
  253. #endif
  254.  
  255. /* ------ Writing ------ */
  256.  
  257. /* Utilities */
  258.  
  259. #define cmd_set_rect(rect)\
  260.   ((rect).x = x, (rect).y = y,\
  261.    (rect).width = width, (rect).height = height)
  262.  
  263. /* Write out the buffered commands, and reset the buffer. */
  264. private int
  265. cmd_write_buffer(gx_device_clist *cldev)
  266. {    FILE *cfile = cldev->cfile;
  267.     FILE *bfile = cldev->bfile;
  268.     int nbands = cldev->nbands;
  269.     gx_clist_state *pcls;
  270.     int band;
  271.     for ( band = 0, pcls = cldev->states; band < nbands; band++, pcls++ )
  272.        {    const cmd_prefix *cp = pcls->head;
  273.         if ( cp != 0 )
  274.            {    cmd_block cb;
  275.             cb.band = band;
  276.             cb.pos = ftell(cfile);
  277.             if_debug2('l', "[l]writing for band %d at %ld\n",
  278.                   band, cb.pos);
  279.             clist_write(bfile, (const byte *)&cb, sizeof(cb));
  280.             pcls->tail->next = 0;    /* terminate the list */
  281.             for ( ; cp != 0; cp = cp->next )
  282.               clist_write(cfile, (const byte *)(cp + 1), cp->size);
  283.             pcls->head = pcls->tail = 0;
  284.             fputc(cmd_opv_end_run, cfile);
  285.            }
  286.        }
  287.     cldev->cnext = cldev->cbuf;
  288.     cldev->ccls = 0;
  289.     return_check_interrupt(0);
  290. }
  291. /* Export under a different name for gxclread.c */
  292. int
  293. clist_flush_buffer(gx_device_clist *cldev)
  294. {    return cmd_write_buffer(cldev);
  295. }
  296.  
  297. /* Add a command to the appropriate band list, */
  298. /* and allocate space for its data. */
  299. /* Return the pointer to the data area. */
  300. private byte *
  301. cmd_put_op(gx_device_clist *cldev, gx_clist_state *pcls, uint size)
  302. {    byte *dp = cldev->cnext;
  303.     if_debug3('L', "[L]band %d: size=%u, left=%u",
  304.           (int)(pcls - cldev->states),
  305.           size, (uint)(cldev->cend - dp));
  306.     if ( size + (sizeof(cmd_prefix) + 4) > cldev->cend - dp )
  307.       { cmd_write_buffer(cldev);
  308.         return cmd_put_op(cldev, pcls, size);
  309.       }
  310.     if ( cldev->ccls == pcls )
  311.       { /* We're adding another command for the same band. */
  312.         /* Tack it onto the end of the previous one. */
  313.         pcls->tail->size += size;
  314.       }
  315.     else
  316.       { cmd_prefix *cp = (cmd_prefix *)(dp + (((byte *)0 - dp) & 3));
  317.         dp = (byte *)(cp + 1);
  318.         if ( pcls->tail != 0 ) pcls->tail->next = cp;
  319.         else pcls->head = cp;
  320.         pcls->tail = cp;
  321.         cldev->ccls = pcls;
  322.         cp->size = size;
  323.       }
  324.     cldev->cnext = dp + size;
  325.     return dp;
  326. }
  327.  
  328. /* Write a variable-size positive integer. */
  329. /* (This works for negative integers also; they are written as though */
  330. /* they were unsigned.) */
  331. #define w1byte(w) (!((w) & ~0x7f))
  332. #define w2byte(w) (!((w) & ~0x3fff))
  333. #define cmd_sizew(w)\
  334.   (w1byte(w) ? 1 : w2byte(w) ? 2 : cmd_w_size((uint)(w)))
  335. #define cmd_sizexy(xy)\
  336.   (w1byte((xy).x | (xy).y) ? 2 :\
  337.    cmd_w_size((uint)(xy).x) + cmd_w_size((uint)(xy).y))
  338. private int near
  339. cmd_w_size(register uint w)
  340. {    register int size = 1;
  341.     while ( w > 0x7f ) w >>= 7, size++;
  342.     return size;
  343. }
  344. #define cmd_putw(w,dp)\
  345.   (w1byte(w) ? (*dp = w, ++dp) :\
  346.    w2byte(w) ? (*dp = (w) | 0x80, dp[1] = (w) >> 7, dp += 2) :\
  347.    (dp = cmd_w_put((uint)(w), dp)))
  348. #define cmd_putxy(xy,dp)\
  349.   (w1byte((xy).x | (xy).y) ? (dp[0] = (xy).x, dp[1] = (xy).y, dp += 2) :\
  350.    (dp = cmd_w_put((uint)(xy).y, cmd_w_put((uint)(xy).x, dp))))
  351. private byte *near
  352. cmd_w_put(register uint w, register byte *dp)
  353. {    while ( w > 0x7f ) *dp++ = w | 0x80, w >>= 7;
  354.     *dp = w;
  355.     return dp + 1;
  356. }
  357.  
  358. /* Write a rectangle. */
  359. private int
  360. cmd_size_rect(register const gx_cmd_rect *prect)
  361. {    return cmd_sizew(prect->x) + cmd_sizew(prect->y) +
  362.         cmd_sizew(prect->width) + cmd_sizew(prect->height);
  363. }
  364. private byte *
  365. cmd_put_rect(register const gx_cmd_rect *prect, register byte *dp)
  366. {    cmd_putw(prect->x, dp);
  367.     cmd_putw(prect->y, dp);
  368.     cmd_putw(prect->width, dp);
  369.     cmd_putw(prect->height, dp);
  370.     return dp;
  371. }
  372.  
  373. /* Write a short bitmap.  1 <= bwidth <= 3. */
  374. private void
  375. cmd_put_short_bits(register byte *dp, register const byte *data,
  376.   int raster, register int bwidth, register int height)
  377. {    while ( --height >= 0 )
  378.        {    switch ( bwidth )
  379.            {
  380.         case 3: dp[2] = data[2];
  381.         case 2: dp[1] = data[1];
  382.         case 1: dp[0] = data[0];
  383.            }
  384.         dp += bwidth, data += raster;
  385.        }
  386. }
  387.  
  388. private int
  389. cmd_write_rect_cmd(gx_device *dev, gx_clist_state *pcls,
  390.   int op, int x, int y, int width, int height)
  391. {    int dx = x - pcls->rect.x;
  392.     int dy = y - pcls->rect.y;
  393.     int dwidth = width - pcls->rect.width;
  394.     int dheight = height - pcls->rect.height;
  395. #define check_ranges_1()\
  396.   ((unsigned)(dx - rmin) <= (rmax - rmin) &&\
  397.    (unsigned)(dy - rmin) <= (rmax - rmin) &&\
  398.    (unsigned)(dwidth - rmin) <= (rmax - rmin))
  399. #define check_ranges()\
  400.   (check_ranges_1() &&\
  401.    (unsigned)(dheight - rmin) <= (rmax - rmin))
  402. #define rmin cmd_min_tiny
  403. #define rmax cmd_max_tiny
  404.     cmd_set_rect(pcls->rect);
  405.     if ( dheight == 0 && check_ranges_1() )
  406.        {    byte *dp = cmd_put_op(cdev, pcls, 2);
  407.         count_op(*dp = op + 0x20 + dwidth - rmin);
  408.         dp[1] = (dx << 4) + dy - (rmin * 0x11);
  409.        }
  410. #undef rmin
  411. #undef rmax
  412. #define rmin cmd_min_short
  413. #define rmax cmd_max_short
  414.     else if ( check_ranges() )
  415.        {    int dh = dheight - cmd_min_tiny;
  416.         byte *dp;
  417.         if ( (unsigned)dh <= cmd_max_tiny - cmd_min_tiny && dh != 0 &&
  418.              dy == 0
  419.            )
  420.            {    op += dh;
  421.             dp = cmd_put_op(cdev, pcls, 3);
  422.            }
  423.         else
  424.            {    dp = cmd_put_op(cdev, pcls, 5);
  425.             dp[3] = dy - rmin;
  426.             dp[4] = dheight - rmin;
  427.            }
  428.         count_op(*dp = op + 0x10);
  429.         dp[1] = dx - rmin;
  430.         dp[2] = dwidth - rmin;
  431.        }
  432.     else
  433.        {    byte *dp = cmd_put_op(cdev, pcls, 1 + cmd_size_rect(&pcls->rect));
  434.         count_op(*dp = op);
  435.         dp = cmd_put_rect(&pcls->rect, dp + 1);
  436.        }
  437.     return 0;
  438. }
  439.  
  440. private void
  441. cmd_put_color(gx_device *dev, gx_clist_state *pcls,
  442.   int op, gx_color_index color)
  443. {    if ( (long)color >= -1 && (long)color <= 13 )
  444.         count_op(*cmd_put_op(cdev, pcls, 1) = op + (int)color + 2);
  445.     else
  446.        {    byte *dp = cmd_put_op(cdev, pcls, 1 + sizeof(color));
  447.         count_op(*dp = op);
  448.         memcpy(dp + 1, &color, sizeof(color));
  449.        }
  450. }
  451. private void
  452. cmd_set_colors(gx_device *dev, gx_clist_state *pcls,
  453.   gx_color_index color0, gx_color_index color1)
  454. {    if ( color0 != pcls->color0 )
  455.        {    cmd_put_color(dev, pcls, cmd_op_set_color0, color0);
  456.         pcls->color0 = color0;
  457.        }
  458.     if ( color1 != pcls->color1 )
  459.        {    cmd_put_color(dev, pcls, cmd_op_set_color1, color1);
  460.         pcls->color1 = color1;
  461.        }
  462. }
  463.  
  464. /* Driver interface */
  465.  
  466. /* Macros for dividing up a single call into bands */
  467. #define BEGIN_RECT\
  468.    {    int yend = y + height;\
  469.     int band_height = cdev->band_height;\
  470.     do\
  471.        {    int band = y / band_height;\
  472.         gx_clist_state *pcls = cdev->states + band;\
  473.         height = band_height - y % band_height;\
  474.         if ( yend - y < height ) height = yend - y;\
  475.            {
  476. #define END_RECT\
  477.            }\
  478.         y += height;\
  479.        }\
  480.     while ( y < yend );\
  481.    }
  482.  
  483. private int
  484. clist_fill_rectangle(gx_device *dev, int x, int y, int width, int height,
  485.   gx_color_index color)
  486. {    fit_fill(dev, x, y, width, height);
  487.     BEGIN_RECT
  488.     if ( color != pcls->color1 )
  489.         cmd_set_colors(dev, pcls, pcls->color0, color);
  490.     cmd_write_rect_cmd(dev, pcls, cmd_op_fill_rect, x, y, width, height);
  491.     END_RECT
  492.     return 0;
  493. }
  494.  
  495. /* Compare unequal tiles.  Return -1 if unrelated, */
  496. /* or 2<=N<=50 for the size of the delta encoding. */
  497. private int
  498. tile_diff(const byte *old_data, const byte *new_data, uint tsize,
  499.   byte _ss *delta)
  500. {    register const ushort *old2, *new2;
  501.     register ushort diff;
  502.     int count;
  503.     register int i;
  504.     byte _ss *pd;
  505.     if ( tsize > 128 ) return -1;
  506.     old2 = (const ushort *)old_data;
  507.     new2 = (const ushort *)new_data;
  508.     count = 0;
  509.     pd = delta + 2;            /* skip slot index */
  510.     for ( i = 0; i < tsize; i += 2, old2++, new2++ )
  511.       if ( (diff = *new2 ^ *old2) != 0 )
  512. #if arch_is_big_endian
  513. #  define i_hi 0
  514. #  define b_0(w) ((w) >> 8)
  515. #  define b_1(w) ((byte)(w))
  516. #else
  517. #  define i_hi 1
  518. #  define b_0(w) ((byte)(w))
  519. #  define b_1(w) ((w) >> 8)
  520. #endif
  521.        {    if ( count == 16 ) return -1;
  522.         if ( diff & 0xff00 )
  523.            {    if ( diff & 0xff )
  524.                 *pd++ = 0x80 + i,
  525.                 *pd++ = b_0(diff),
  526.                 *pd++ = b_1(diff);
  527.             else
  528.                 *pd++ = i + i_hi, *pd++ = diff >> 8;
  529.            }
  530.         else            /* know diff != 0 */
  531.             *pd++ = i + (1 - i_hi), *pd++ = (byte)diff;
  532.         count++;
  533.        }
  534. #undef b_0
  535. #undef b_1
  536. #undef i_hi
  537.     if ( count == 0 )
  538.     {    /* Tiles are identical.  This is highly unusual, */
  539.         /* but not impossible. */
  540.         pd[0] = pd[1] = 0;
  541.         pd += 2;
  542.         count = 1;
  543.     }
  544.     delta[0] = (byte)cmd_op_delta_tile_bits + count - 1;
  545.     return pd - delta;
  546. }
  547.  
  548. /* Handle changing tiles for clist_tile_rectangle. */
  549. /* We put this in a separate routine, even though it is called only once, */
  550. /* to avoid cluttering up the main-line case of tile_rectangle. */
  551. private int
  552. clist_change_tile(gx_device_clist *cldev, gx_clist_state *pcls,
  553.   const gx_bitmap *tile)
  554. {    uint tile_size = tile->raster * tile->size.y;
  555.     tile_slot *old_tile, *new_tile;
  556.     int slot_index;
  557.     /* Look up the tile in the cache. */
  558. top:       {    gx_bitmap_id id = tile->id;
  559.         uint probe = (uint)(id >> 16) + (uint)(id);
  560.         old_tile = pcls->tile;
  561.         for ( ; ; probe += 25 /* semi-random odd # */ )
  562.            {    tile_hash *hptr = cldev->tile_hash_table +
  563.               (probe & cldev->tile_hash_mask);
  564.             if ( (slot_index = hptr->slot_index) < 0 ) /* empty entry */
  565.                {    /* Must change tiles.  Check whether the */
  566.                 /* tile size has changed. */
  567.                 if ( tile->size.x != cldev->tile.size.x ||
  568.                      tile->size.y != cldev->tile.size.y
  569.                    )
  570.                    {    if ( tile->raster !=
  571.                          ((tile->size.x + 31) >> 5) << 2 ||
  572.                          tile_size > cldev->tile_max_size
  573.                        )
  574.                         return -1;
  575.                     cldev->tile = *tile;    /* reset size, raster */
  576.                     clist_init_tiles(cldev);
  577.                     goto top;
  578.                    }
  579.                 if ( cldev->tile_count == cldev->tile_max_count )
  580.                    {    /* Punt. */
  581.                     clist_init_tiles(cldev);
  582.                     goto top;
  583.                    }
  584.                 hptr->slot_index = slot_index =
  585.                   cldev->tile_count++;
  586.                 new_tile = tile_slot_ptr(cldev, slot_index);
  587.                 new_tile->id = id;
  588.                 memcpy(ts_bits(cldev, new_tile), tile->data, tile_size);
  589.                 count_add1(cmd_tile_added);
  590.                 if_debug3('L', "[L]adding tile %d, hash=%d, id=%lx\n",
  591.                      slot_index,
  592.                      (int)(hptr - cldev->tile_hash_table),
  593.                      id);
  594.                 break;
  595.                }
  596.             new_tile = tile_slot_ptr(cldev, slot_index);
  597.             if ( new_tile->id == id )
  598.                {    count_add1(cmd_tile_found);
  599.                 if_debug1('L', "[L]found tile %d\n",
  600.                       slot_index);
  601.                 break;
  602.                }
  603.            }
  604.        }
  605.     /* Check whether this band knows about this tile yet. */
  606.        {    int band_index = pcls - cldev->states;
  607.         byte pmask = 1 << (band_index & 7);
  608.         byte *ppresent = ts_mask(new_tile) + (band_index >> 3);
  609.         if ( *ppresent & pmask )
  610.            {    /* Tile is known, just put out the index. */
  611.             byte *dp = cmd_put_op(cldev, pcls, 2);
  612.             count_op(*dp = cmd_op_set_tile_index);
  613.             dp[1] = slot_index;
  614.            }
  615.         else
  616.            {    /* Tile is not known, put out the bits.  Use a */
  617.             /* delta encoding or a short encoding if possible. */
  618.             byte *new_data = ts_bits(cldev, new_tile);
  619.             byte *dp;
  620.             byte delta[2+16*3];
  621.             int diff;
  622.             *ppresent |= pmask;
  623.             if ( old_tile != &no_tile &&
  624.                  (diff = tile_diff(ts_bits(cldev, old_tile), new_data, tile_size, delta)) >= 0
  625.                )
  626.                {    /* Use delta representation */
  627.                 dp = cmd_put_op(cldev, pcls, diff);
  628.                 count_op(delta[0]);
  629.                 delta[1] = slot_index;
  630.                 memcpy(dp, delta, diff);
  631.                 count_add(cmd_delta_tile_count, diff - 2);
  632.                }
  633.             else
  634.                {    if ( old_tile == &no_tile )
  635.                    {    byte *dp = cmd_put_op(cldev, pcls,
  636.                         1 + cmd_sizexy(cldev->tile.size));
  637.                     count_op(*dp++ = (byte)cmd_opv_set_tile_size);
  638.                     cmd_putxy(cldev->tile.size, dp);
  639.                    }
  640.                 if ( tile->size.x <= 16 )
  641.                    {    dp = cmd_put_op(cldev, pcls, 2 + (tile_size >> 1));
  642.                     cmd_put_short_bits(dp + 2, new_data, tile->raster, 2, tile->size.y);
  643.                     count_add(cmd_tile_count, tile_size >> 1);
  644.                    }
  645.                 else
  646.                    {    dp = cmd_put_op(cldev, pcls, 2 + tile_size);
  647.                     memcpy(dp + 2, new_data, tile_size);
  648.                     count_add(cmd_tile_count, tile_size);
  649.                    }
  650.                 count_op(*dp = (byte)cmd_op_set_tile_bits);
  651.                 dp[1] = slot_index;
  652.                }
  653.            }
  654.        }
  655.     pcls->tile = new_tile;
  656.     return 0;
  657. }
  658. private int
  659. clist_tile_rectangle(gx_device *dev, const gx_bitmap *tile, int x, int y,
  660.   int width, int height, gx_color_index color0, gx_color_index color1,
  661.   int px, int py)
  662. {    fit_fill(dev, x, y, width, height);
  663.     BEGIN_RECT
  664.     if ( tile->id != pcls->tile->id )
  665.        {    if ( clist_change_tile(cdev, pcls, tile) < 0 )
  666.             return gx_default_tile_rectangle(dev, tile, x, y, width, height, color0, color1, px, py);
  667.        }
  668.     if ( color0 != pcls->color0 || color1 != pcls->color1 )
  669.         cmd_set_colors(dev, pcls, color0, color1);
  670.     if ( px != pcls->tile_phase.x || py != pcls->tile_phase.y )
  671.        {    byte *dp = cmd_put_op(cdev, pcls, 1 + cmd_sizexy(pcls->tile_phase));
  672.         count_op(*dp++ = (byte)cmd_opv_set_tile_phase);
  673.         pcls->tile_phase.x = px;
  674.         pcls->tile_phase.y = py;
  675.         cmd_putxy(pcls->tile_phase, dp);
  676.        }
  677.     cmd_write_rect_cmd(dev, pcls, cmd_op_tile_rect, x, y, width, height);
  678.     END_RECT
  679.     return 0;
  680. }
  681.  
  682. private int
  683. clist_copy_mono(gx_device *dev,
  684.     const byte *data, int data_x, int raster, gx_bitmap_id id,
  685.     int x, int y, int width, int height,
  686.     gx_color_index color0, gx_color_index color1)
  687. {    int y0;
  688.     fit_copy(dev, data, data_x, raster, id, x, y, width, height);
  689.     y0 = y;
  690.     BEGIN_RECT
  691.     gx_cmd_rect rect;
  692.     uint dsize;
  693.     int rsize;
  694.     int bwidth;
  695.     const byte *row = data + (y - y0) * raster;
  696.     byte *dp;
  697.     if ( color0 != pcls->color0 || color1 != pcls->color1 )
  698.         cmd_set_colors(dev, pcls, color0, color1);
  699.     cmd_set_rect(rect);
  700.     rsize = cmd_size_rect(&rect);
  701.     if ( width >= 2 && (bwidth = (width + (data_x & 7) + 7) >> 3) <= 3 &&
  702.          height <= 255 &&
  703.          height <= (cbuf_size - cmd_largest_size) / align_bitmap_mod
  704.        )
  705.        {    dsize = height * bwidth;
  706.         dp = cmd_put_op(cdev, pcls, 1 + rsize + dsize);
  707.         count_op(*dp++ = (byte)cmd_op_copy_mono + (data_x & 7) + 1);
  708.         dp = cmd_put_rect(&rect, dp);
  709.         row += data_x >> 3;
  710.         cmd_put_short_bits(dp, row, raster, bwidth, height);
  711.         pcls->rect = rect;
  712.         count_add(cmd_copy_count, dsize);
  713.        }
  714.     else
  715.        {    dsize = height * raster;
  716.         if ( dsize > cbuf_size )
  717.            {    /* We have to split it into pieces. */
  718.             if ( height > 1 )
  719.                {    int h2 = height >> 1;
  720.                 clist_copy_mono(dev, row, data_x, raster,
  721.                     gx_no_bitmap_id, x, y, width, h2,
  722.                     color0, color1);
  723.                 clist_copy_mono(dev, row + h2 * raster,
  724.                     data_x, raster, gx_no_bitmap_id,
  725.                     x, y + h2, width, height - h2,
  726.                     color0, color1);
  727.                }
  728.             else
  729.             /* Split a single (very long) row. */
  730.                {    int w2 = width >> 1;
  731.                 clist_copy_mono(dev, row, data_x, raster,
  732.                     gx_no_bitmap_id, x, y, w2, 1,
  733.                     color0, color1);
  734.                 clist_copy_mono(dev, row, data_x + w2,
  735.                     raster, gx_no_bitmap_id, x + w2, y,
  736.                     width - w2, 1, color0, color1);
  737.                }
  738.            }
  739.         else
  740.         {    dp = cmd_put_op(cdev, pcls, 1 + rsize + cmd_sizew(data_x) + cmd_sizew(raster) + dsize);
  741.             count_op(*dp++ = (byte)cmd_op_copy_mono);
  742.             dp = cmd_put_rect(&rect, dp);
  743.             cmd_putw(data_x, dp);
  744.             cmd_putw(raster, dp);
  745.             memcpy(dp, row, dsize);
  746.             pcls->rect = rect;
  747.             count_add(cmd_copy_count, dsize);
  748.         }
  749.        }
  750.     END_RECT
  751.     return 0;
  752. }
  753.  
  754. private int
  755. clist_copy_color(gx_device *dev,
  756.     const byte *data, int data_x, int raster, gx_bitmap_id id,
  757.     int x, int y, int width, int height)
  758. {    int y0;
  759.     fit_copy(dev, data, data_x, raster, id, x, y, width, height);
  760.     y0 = y;
  761.     BEGIN_RECT
  762.     gx_cmd_rect rect;
  763.     uint dsize = height * raster;
  764.     const byte *row = data + (y - y0) * raster;
  765.     byte *dp;
  766.     if ( dsize > cbuf_size )
  767.        {    /* We have to split it into pieces. */
  768.         if ( height > 1 )
  769.            {    int h2 = height >> 1;
  770.             clist_copy_color(dev, row, data_x, raster,
  771.                 gx_no_bitmap_id, x, y, width, h2);
  772.             clist_copy_color(dev, row + h2 * raster, data_x,
  773.                 raster, gx_no_bitmap_id, x, y + h2, width, height - h2);
  774.            }
  775.         else
  776.            {    /* Split a single (very long) row. */
  777.             int w2 = width >> 1;
  778.             clist_copy_color(dev, row, data_x, raster,
  779.                 gx_no_bitmap_id, x, y, w2, 1);
  780.             clist_copy_color(dev, row, data_x + w2,
  781.                 raster, gx_no_bitmap_id, x + w2, y,
  782.                 width - w2, 1);
  783.            }
  784.        }
  785.     else
  786.     {    cmd_set_rect(rect);
  787.         dp = cmd_put_op(cdev, pcls, 1 + cmd_size_rect(&rect) + cmd_sizew(data_x) + cmd_sizew(raster) + dsize);
  788.         count_op(*dp++ = (byte)cmd_op_copy_color);
  789.         dp = cmd_put_rect(&rect, dp);
  790.         pcls->rect = rect;
  791.         cmd_putw(data_x, dp);
  792.         cmd_putw(raster, dp);
  793.         memcpy(dp, row, dsize);
  794.         count_add(cmd_copy_count, dsize);
  795.     }
  796.     END_RECT
  797.     return 0;
  798. }
  799.